﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.ExceptionHandling;

using OF.Utility;
using OF.Utility.Logging;

namespace User.Api.Common
{
    public class GlobalExceptionLogger : ExceptionLogger
    {
        private const string HttpContextBaseKey = "MS_HttpContext";

        public override void Log(ExceptionLoggerContext context)
        {
            if (!ShouldLog(context))
            {
                return;
            }
            // Retrieve the current HttpContext instance for this request.
            HttpContext httpContext = GetHttpContext(context.Request);

            if (httpContext == null)
            {
                return;
            }
            // Wrap the exception in an HttpUnhandledException so that ELMAH can capture the original error page.
            //Exception exceptionToRaise = new HttpUnhandledException(message: null, innerException: context.Exception);
            // Send the exception to ELMAH (for logging, mailing, filtering, etc.).
            //ErrorSignal signal = ErrorSignal.FromContext(httpContext);
            //signal.Raise(exceptionToRaise, httpContext);
            ErrorLog log = new ErrorLog();
            //log.UA = HttpContext.Current.Request.UserAgent;
            //log.RequestMethod = context.Request.Method.Method;
            //if (log.RequestMethod.Equals("POST", StringComparison.Ordinal))
            //{
            //    log.PostData = GetPostData(context.ExceptionContext.ActionContext);
            //}
            //log.RequestUrl = context.Request.RequestUri.AbsoluteUri;
            //log.ClientIP = IPHelper.IPAddress;
            //log.ErrorSource = context.Exception.Source;
            //log.ErrorMessage = context.Exception.Message;
            //log.ErrorTrace = context.Exception.StackTrace;
            ErrorLogHelper.Error(context.Exception);
        }
        /// <summary>
        /// 获取制定的header值
        /// </summary>
        /// <param name="actionContext"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public string GetHeaderValue(HttpActionContext actionContext, string name)
        {
            IEnumerable<string> headers;
            if (actionContext.Request.Headers.TryGetValues(name, out headers))
            {
                return headers.FirstOrDefault();

            }
            return "";
        }

        /// <summary>
        /// 获取post数据
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        protected string GetPostData(HttpActionContext actionContext)
        {
            return actionContext.Request.Content.ReadAsStringAsync().Result;
        }
        private static HttpContext GetHttpContext(HttpRequestMessage request)
        {
            HttpContextBase contextBase = GetHttpContextBase(request);

            if (contextBase == null)
            {
                return null;
            }

            return ToHttpContext(contextBase);
        }

        private static HttpContextBase GetHttpContextBase(HttpRequestMessage request)
        {
            if (request == null)
            {
                return null;
            }

            object value;

            if (!request.Properties.TryGetValue(HttpContextBaseKey, out value))
            {
                return null;
            }

            return value as HttpContextBase;
        }

        private static HttpContext ToHttpContext(HttpContextBase contextBase)
        {
            return contextBase.ApplicationInstance.Context;
        }
        public override bool ShouldLog(ExceptionLoggerContext context)
        {
            bool bReturn = true;
            if (BusinessException.IsBusinessException(context.Exception))
            {
                bReturn = false;
            }
            else if (context.ExceptionContext.ActionContext != null)
            {
                bReturn = false;
            }
            return bReturn;
        }
    }
    /// <summary>
    /// 全局异常处理器
    /// </summary>
    public class GlobalExceptionHandler : ExceptionHandler
    {
        public override void Handle(ExceptionHandlerContext context)
        {
            context.Result = new InternalServerErrorTextPlainResult(
                "An unhandled exception occurred; check the log for more information.",
                Encoding.UTF8, context.Request);
        }
    }

    public class InternalServerErrorTextPlainResult : IHttpActionResult
    {
        public InternalServerErrorTextPlainResult(string content, Encoding encoding, HttpRequestMessage request)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            if (encoding == null)
            {
                throw new ArgumentNullException("encoding");
            }

            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            Content = content;
            Encoding = encoding;
            Request = request;
        }

        public string Content { get; }

        public Encoding Encoding { get; }

        public HttpRequestMessage Request { get; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(Execute());
        }

        private HttpResponseMessage Execute()
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            response.RequestMessage = Request;
            response.Content = new StringContent(Content, Encoding);
            return response;
        }
    }
}